package com.zmn.plat.business.impl.product;

import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.plat.business.interfaces.channel.ChannelCategBService;
import com.zmn.plat.business.interfaces.channel.ChannelServiceCategoryBService;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceBService;
import com.zmn.plat.business.interfaces.product.ProductBService;
import com.zmn.plat.business.interfaces.product.ProductCache;
import com.zmn.plat.business.interfaces.product.ProductDetailsBService;
import com.zmn.plat.business.interfaces.product.ServProductBService;
import com.zmn.plat.business.interfaces.product.tariff.TariffProductBService;
import com.zmn.plat.business.interfaces.servcategory.ShowCategoryAssociationBService;
import com.zmn.plat.business.interfaces.service.tariff.ServiceTariffBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.product.*;
import com.zmn.plat.common.dto.product.base.ProductBaseDRO;
import com.zmn.plat.common.dto.product.base.ProductBaseSimpleDRO;
import com.zmn.plat.common.dto.product.item.ItemDRO;
import com.zmn.plat.common.dto.product.picture.ProductGuaranteeDRO;
import com.zmn.plat.common.dto.product.picture.ServProductPictureDRO;
import com.zmn.plat.common.dto.product.price.ProductPriceDRO;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.manager.interfaces.cache.AreaCache;
import com.zmn.plat.model.entity.area.BaseArea;
import com.zmn.plat.model.entity.category.BaseCategory;
import com.zmn.plat.model.entity.category.BaseCategoryQuery;
import com.zmn.plat.model.entity.category.ServCategAndCategTwoQuery;
import com.zmn.plat.model.entity.pilot.SupportPilotVO;
import com.zmn.plat.model.entity.product.ProductQuery;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductPicture;
import com.zmn.plat.model.entity.product.ServProductQuery;
import com.zmn.plat.model.entity.product.guarantee.ProductGuarantee;
import com.zmn.plat.model.entity.servcategory.ServCategory;
import com.zmn.plat.model.entity.servcategory.ShowCategoryAssociationVO;
import com.zmn.plat.model.entity.service.tariff.ServiceTariff;
import com.zmn.plat.model.vo.product.ProductAllMsgVO;
import com.zmn.plat.model.vo.product.tariff.item.price.ProductServiceItemExcutePriceQueryVo;
import com.zmn.plat.model.vo.product.tariff.item.price.ProductServiceItemExcutePriceResultVo;
import com.zmn.plat.services.interfaces.category.BaseCategoryService;
import com.zmn.plat.services.interfaces.product.ServProductPictureService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import com.zmn.plat.services.interfaces.product.guarantee.ProductGuaranteeService;
import com.zmn.plat.services.interfaces.servcategory.ServCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : tanghongjun
 * @since 2018/7/12 16:15
 */
@Service
@Slf4j
public class ProductBServiceImpl implements ProductBService {

    @Resource
    ProductCache productCache;
    @Resource
    AreaCache areaCache;
    @Resource
    ServProductPictureService servProductPictureService;
    @Resource
    ProductGuaranteeService productGuaranteeService;
    @Resource
    ServProductService servProductService;
    @Resource
    ChannelPriceBService channelPriceBService;
    @Resource
    ServiceTariffBService faultTariffBService;
    @Resource
    TariffProductBService tariffProductBService;
    @Resource
    ShowCategoryAssociationBService showCategoryAssociationBService;
    @Resource
    ServProductBService servProductBService;
    @Resource
    BaseCategoryService baseCategoryService;
    @Resource
    ServCategoryService servCategoryService;
    @Resource
    ProductBService productBService;
    @Resource
    ProductDetailsBService productDetailsBService;
    @Resource
    ChannelCategBService channelCategBService;
    @Resource
    ChannelServiceCategoryBService channelServiceCategoryBService;


    @Override
    public Boolean checkTraiffByChannelAndCityAndProductAndType(Integer channelId, Integer cityId, Integer productId, Integer type) throws PlatException {
        if (Objects.isNull(channelId) || Objects.isNull(cityId) || Objects.isNull(productId) || Objects.isNull(type)) {
            log.error("入参不能为空, channelId:{}, cityId:{}, productId:{}, type:{}", channelId, cityId, productId, type);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServProduct servProduct = servProductService.findByKey(productId);
        if (Objects.isNull(servProduct)) {
            log.error("产品不存在，" + PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
        }

        boolean isTariffChannel = false;

        // 如果是后端产品，转换成前端产品分类
        if (Objects.equals(servProduct.getShowType(), ProductConsts.ERP_PRODUCT_TYPE)) {
            List<ShowCategoryAssociationVO> showCategoryAssociationVOS =
                    showCategoryAssociationBService.listByCategoryId(servProduct.getServCategId(), servProduct.getCategOneId(), servProduct.getCategId());
            if (CollectionUtil.isNotNullOrEmpty(showCategoryAssociationVOS)) {
                isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, OnePriceConsts.TARIFF,
                        showCategoryAssociationVOS.get(0).getShowServCategId(), showCategoryAssociationVOS.get(0).getShowCategId());
            }
        } else {
            isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, OnePriceConsts.TARIFF, servProduct.getServCategId(), servProduct.getCategId());
        }

        if (isTariffChannel) {
            log.info(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "");
            isTariffChannel = checkTariffByProductIdAndShowType(servProduct, channelId, servProduct.getShowType(), type);
        }

        return isTariffChannel;
    }

    @Override
    public List<ProductAllMsgInfoDRO> listByDIO(ProductDIO productDIO) throws PlatException {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(productDIO.getType()) && !NumberUtil.isPositiveInteger(productDIO.getBizType())) {
            productDIO.setBizType(productDIO.getType());
        }

        // 参数校验
        // 如果需要价格信息，渠道ID和城市ID不能为空
        Boolean needPriceMsg = Objects.isNull(productDIO.getNeedPriceMsg()) || Objects.equals(productDIO.getNeedPriceMsg(), false); // ->Objects.equals(productDIO.getNeedPriceMsg(), true) 重构优化
        Boolean cityAndChannelFlag = Objects.isNull(productDIO.getChannelId()) || Objects.isNull(productDIO.getCityId()) || Objects.isNull(productDIO.getBizType());
        if (Objects.equals(needPriceMsg, false) && cityAndChannelFlag) {
            log.error("需要价格信息，渠道ID和城市ID不能为空" + PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_CITYID_OR_CHANNELID);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_CITYID_OR_CHANNELID);
        }

        // 查询产品基础信息 修改了查询逻辑 2021-11-17 17:52:59
        List<ProductBaseDRO> productBaseDROList = productDetailsBService.listBaseDROByDIO(productDIO);
        if (CollectionUtils.isEmpty(productBaseDROList)) {
            log.error("没有相关产品信息" + PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
        }

        List<Integer> productIdList = new ArrayList<>(productBaseDROList.size());
        Map<Integer, ProductBaseDRO> productBaseDROMap = new HashMap<>(productBaseDROList.size());
        ProductBaseDRO productBaseDRO;
        for (int i = 0; i < productBaseDROList.size(); i++) {
            productBaseDRO = productBaseDROList.get(i);
            productIdList.add(productBaseDRO.getProductId());
            productBaseDROMap.put(productBaseDRO.getProductId(), productBaseDRO);
        }

        // 查询产品图片信息
        Map<Integer, ServProductPictureDRO> productPictureDROMap = new HashMap<>(productIdList.size());
        if (Objects.nonNull(productDIO.getNeedPictureMsg()) && productDIO.getNeedPictureMsg() && CollectionUtils.isNotEmpty(productIdList)) {
            List<ServProductPictureDRO> servProductPictureDROList = productBService.listProductPictureByIdList(productIdList);
            for (int i = 0; i < servProductPictureDROList.size(); i++) {
                productPictureDROMap.put(servProductPictureDROList.get(i).getProductId(), servProductPictureDROList.get(i));
            }
        }

        // 查询产品保障信息
        Map<Integer, ProductGuaranteeDRO> productGuaranteeDROMap = new HashMap<>(productIdList.size());
        if (Objects.nonNull(productDIO.getNeedGuaranteeMsg()) && productDIO.getNeedGuaranteeMsg() && CollectionUtils.isNotEmpty(productIdList)) {
            List<ProductGuaranteeDRO> servProductGuaranteeDROList = productBService.listProductGuaranteeByIdList(productIdList);
            for (int i = 0; i < servProductGuaranteeDROList.size(); i++) {
                productGuaranteeDROMap.put(servProductGuaranteeDROList.get(i).getProductId(), servProductGuaranteeDROList.get(i));
            }
        }

        // 查询产品价格信息
        Map<Integer, ProductPriceDRO> productPriceDROMap = new HashMap<>(productIdList.size());
        if (Objects.nonNull(productDIO.getNeedPriceMsg()) && productDIO.getNeedPriceMsg() && CollectionUtils.isNotEmpty(productIdList)) {
            List<ProductPriceDRO> productPriceDROList = productBService.listProductPriceByIdListAndChannelAndCityAndShowTypeAndTypeAndBrand(productIdList, productDIO.getChannelId(),
                    productDIO.getCityId(), productDIO.getShowType(), productDIO.getBizType(), productDIO.getIsTariffChannel(), productDIO.getBrandId());
            for (int i = 0; i < productPriceDROList.size(); i++) {
                productPriceDROMap.put(productPriceDROList.get(i).getProductId(), productPriceDROList.get(i));
            }
        }

        // 返回产品信息
        List<ProductAllMsgInfoDRO> productAllMsgInfoDROList = new ArrayList<>(productIdList.size());
        ProductAllMsgInfoDRO productAllMsgInfoDRO;
        int productId;
        for (int i = 0; i < productIdList.size(); i++) {
            productId = productIdList.get(i);
            productAllMsgInfoDRO = new ProductAllMsgInfoDRO();
            if (Objects.nonNull(productBaseDROMap.get(productId))) {
                productAllMsgInfoDRO.setProductBaseDRO(productBaseDROMap.get(productId));
            }
            if (Objects.nonNull(productDIO.getNeedPictureMsg()) && productDIO.getNeedPictureMsg() && Objects.nonNull(productPictureDROMap.get(productId))) {
                productAllMsgInfoDRO.setServProductPictureDRO(productPictureDROMap.get(productId));
            }
            if (Objects.nonNull(productDIO.getNeedGuaranteeMsg()) && productDIO.getNeedGuaranteeMsg() && Objects.nonNull(productGuaranteeDROMap.get(productId))) {
                productAllMsgInfoDRO.setProductGuaranteeDRO(productGuaranteeDROMap.get(productId));
            }
            if (Objects.nonNull(productDIO.getNeedPriceMsg()) && productDIO.getNeedPriceMsg() && Objects.nonNull(productPriceDROMap.get(productId))) {
                productAllMsgInfoDRO.setProductPriceDRO(productPriceDROMap.get(productId));
            }
            productAllMsgInfoDROList.add(productAllMsgInfoDRO);
        }

        return productAllMsgInfoDROList;
    }

    @Override
    public List<ProductAllMsgInfoExtDRO> listExtInfoByDIO(ProductDIO productDIO) throws PlatException {
        List<ProductAllMsgInfoDRO> allMsgInfoDROS = productBService.listByDIO(productDIO);
        List<ProductAllMsgInfoExtDRO> retList = new ArrayList<>(allMsgInfoDROS.size());
        Map<Integer, List<ProductBaseSimpleDRO>> servCategMap = new HashMap<>();
        for (ProductAllMsgInfoDRO infoDRO : allMsgInfoDROS) {
            ProductAllMsgInfoExtDRO resultDRO = copyFromDRO(infoDRO);
            // 只针对一个产品
            ProductBaseDRO mainDRO = infoDRO.getProductBaseDRO();
            List<ProductBaseSimpleDRO> simpleDROList = servCategMap.get(mainDRO.getServCategId());
            if (Objects.isNull(simpleDROList)) {
                ProductDIO query = new ProductDIO();
                query.setChannelId(productDIO.getChannelId());
                query.setCityId(productDIO.getCityId());
                query.setServCategIds(Arrays.asList(mainDRO.getServCategId()));
                query.setCategIds(Arrays.asList(mainDRO.getCategId()));
                query.setStatus(GlobalConsts.YES);
                query.setBizType(productDIO.getBizType());
                query.setShowType(productDIO.getShowType());
                query.setDefaultType(GlobalConsts.NO);
                // 查询产品基础信息 修改了查询逻辑 2021-11-17 17:52:59
                List<ProductBaseDRO> productOneBaseDROList = productDetailsBService.listBaseDROByDIO(productDIO);
                if (CollectionUtils.isNotEmpty(productOneBaseDROList)) {
                    simpleDROList = productOneBaseDROList.stream().map(e -> new ProductBaseSimpleDRO(e.getProductId(), e.getName())).collect(Collectors.toList());
                    resultDRO.setSameServCategProductBaseDROList(simpleDROList);
                    servCategMap.put(mainDRO.getServCategId(), simpleDROList);
                }
            } else {
                resultDRO.setSameServCategProductBaseDROList(simpleDROList);
            }
            retList.add(resultDRO);
        }
        return retList;
    }

    private ProductAllMsgInfoExtDRO copyFromDRO(ProductAllMsgInfoDRO allMsgInfoDRO) {
        ProductAllMsgInfoExtDRO dro = new ProductAllMsgInfoExtDRO();
        dro.setProductBaseDRO(allMsgInfoDRO.getProductBaseDRO());
        dro.setProductGuaranteeDRO(allMsgInfoDRO.getProductGuaranteeDRO());
        dro.setProductPriceDRO(allMsgInfoDRO.getProductPriceDRO());
        dro.setServProductPictureDRO(allMsgInfoDRO.getServProductPictureDRO());
        return dro;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:price:ids:'+#p0+':channel:'+#p1+':city:'+#p2+':showtype:'+#p3+':type:'+#p4+':tariff:'+#p5+':brand:'+#p6", unless = "#result == null")
    public List<ProductPriceDRO> listProductPriceByIdListAndChannelAndCityAndShowTypeAndTypeAndBrand(List<Integer> productIdList, Integer channelId, Integer cityId, Integer showType, Integer bizType,
                                                                                                     Boolean isTariffChannel, Integer brandId) {
        if (CollectionUtils.isEmpty(productIdList) || Objects.isNull(channelId) || Objects.isNull(cityId) || Objects.isNull(showType) || Objects.isNull(bizType)) {
            log.error("参数不合法：productIdList={}，channelId={},cityId={},showType={},bizType={}", productIdList, channelId, cityId, showType, bizType);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        BaseArea baseArea = areaCache.getArea(cityId);

        if (Objects.isNull(baseArea)) {
            log.error("城市对应的数据不存在.cityId={},errorCode:{}", cityId, PlatErrorCodeDict.ERROR_CODE_PRODUCT_PRODUCT_NO_AREA);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_PRODUCT_NO_AREA);
        }

        Integer productId;
        ProductPriceDRO productPriceDRO;
        List<ProductPriceDRO> productPriceDROList = new ArrayList<>();
        for (int i = 0; i < productIdList.size(); i++) {
            productId = productIdList.get(i);
            productPriceDRO = productBService.getProductPriceByIdAndChannelAndCityAndShowTypeAndTypeAndBrand(productId, channelId, baseArea, showType, bizType, isTariffChannel, brandId);
            if (Objects.isNull(productPriceDRO)) {
                continue;
            }

            productPriceDROList.add(productPriceDRO);
        }

        return productPriceDROList;
    }

    /**
     * 描述: 根据产品ID，渠道ID，城市信息，产品展示类型，保内保外，是否默认支持计价器，品牌ID获取产品价格信息
     * <p>
     * 备注：1.优先取定金(定金是配置在一口价上面的，所以要先查询一口价是否配置)，如果该产品在指定的渠道城市下存在定金（定金和服务分类强关联，产品必须在服务分类下），返回定金
     * 2.渠道，城市，产品是否支持计价器，
     * 2.1 支持，查询计价器价格表是否存在（后台产品必须唯一），不存在返回；存在则查询是否存在默认的服务项，存在返回默认项目对应的价格，不存在直接返回；
     * 2.2 不支持，查询服务项价格表是否存在（后台产品必须唯一），不存在返回；存在则查询是否存在默认的服务项，存在返回默认项目对应的价格，不存在直接返回；
     *
     * @param productId       产品ID
     * @param channelId       渠道ID
     * @param baseArea        城市信息
     * @param showType        产品展示类型:1.后台，2.前台，3.计价器
     * @param type            1保外，2.保内
     * @param isTariffChannel 是否默认支持计价器渠道
     * @param brandId         品牌ID
     * @return ProductPriceDRO 产品价格信息
     * @auther tanghongjun
     * @since 2020/3/28 14:51
     */
    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:price:id:'+#p0+':channel:'+#p1+':city:'+#p2+':showtype:'+#p3+':type:'+#p4+':tariff:'+#p5+':brand:'+#p6", unless = "#result == null")
    public ProductPriceDRO getProductPriceByIdAndChannelAndCityAndShowTypeAndTypeAndBrand(Integer productId, Integer channelId, BaseArea baseArea, Integer showType, Integer type,
                                                                                          Boolean isTariffChannel, Integer brandId) {
        ProductPriceDRO productPriceDRO = new ProductPriceDRO();
        productPriceDRO.setProductId(productId);
        ServProduct servProduct = servProductService.findByKey(productId);
        Integer payType = null;

        if (Objects.isNull(servProduct)) {
            log.error("产品不存在，productId={}，errorCode:{}", productId, PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
        }

        // 查询定金
        SupportPilotVO supportPilotVO1 = channelPriceBService.listPilotCategs(channelId, baseArea.getAreaId(), OnePriceConsts.ONE_PRICE, servProduct.getServCategId(), servProduct.getCategId());
        if (Objects.nonNull(supportPilotVO1) && NumberUtil.isNotNullOrZero(supportPilotVO1.getEarnestPrice())) {
            // 支持定金
            productPriceDRO.setPayType(GlobalConsts.NO);
            productPriceDRO.setEarnestPrice(supportPilotVO1.getEarnestPrice());
            return productPriceDRO;
        }

        // 如果不是默认计价器渠道，校验试点配置中该渠道该城市是否支持计价器
        if (Objects.isNull(isTariffChannel) || Objects.equals(isTariffChannel, false)) {
            isTariffChannel = false;
            // 如果是后端产品，转换成前端产品分类
            if (Objects.equals(servProduct.getShowType(), ProductConsts.ERP_PRODUCT_TYPE)) {
                List<ShowCategoryAssociationVO> showCategoryAssociationVOS =
                        showCategoryAssociationBService.listByCategoryId(servProduct.getServCategId(), servProduct.getCategOneId(), servProduct.getCategId());
                if (CollectionUtil.isNotNullOrEmpty(showCategoryAssociationVOS)) {
                    isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, baseArea.getAreaId(), OnePriceConsts.TARIFF,
                            showCategoryAssociationVOS.get(0).getShowServCategId(), showCategoryAssociationVOS.get(0).getShowCategId());
                }
            } else {
                isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, baseArea.getAreaId(), OnePriceConsts.TARIFF, servProduct.getServCategId(), servProduct.getCategId());
            }
        }

        // 如果支持计价器，判断是否计价器产品属性：
        // 如果是前台产品，则判断是否有关联的后台产品开通计价器，并且开通计价器的后台产品是否有关联上架的计价器产品，并且是否有可用的计价器价格表
        // 如果是后台产品，则查询是否开通计价器状态，并且有对应开通上架的计价器产品，并且有对应的开通的前台产品，并且是否有可用的计价器价格表
        // 如果是计价器产品，则查询是否上架，其对应的后台产品是有否开通计价器状态的后台产品，开通后台计价器状态的后台产品是否有上架的前台产品，开通计价器状态的后台产品是否有可用的计价器价格表
        if (isTariffChannel) {
            log.info(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "");
            isTariffChannel = checkTariffByProductIdAndShowType(servProduct, channelId, showType, type);
        }


        // 如果支持计价器
        if (isTariffChannel) {
            // 查询价格表信息
            ServiceTariff faultTariff = faultTariffBService.getTariffByChannelIdAndProductIdAndShowTypeAndType(channelId, productId, ProductDict.TRIFF_TYPE_TARIFF, showType, type);

            // 产品不支持一口价
            if (Objects.isNull(faultTariff)) {
                log.info(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_NULL + "");
                productPriceDRO.setFixedPrice(GlobalConsts.NO);
                return productPriceDRO;
            }

            // 查询价格表是否有默认的一口价服务项
            ProductServiceItemExcutePriceResultVo productFaultItemExcutePriceResultVo =
                    productBService.getDaultPriceItem(ProductDict.TRIFF_TYPE_TARIFF, servProduct, showType, channelId, type, brandId, baseArea.getAreaId());
            if (Objects.nonNull(productFaultItemExcutePriceResultVo)) {
                ProductPriceDRO priceDRO = this.setFixedPriceMsg(productPriceDRO, productFaultItemExcutePriceResultVo);
                priceDRO.setPayType(payType);
                return priceDRO;
            }

        }

        // 如果不支持计价器
        if (!isTariffChannel) {
            // 查询价格表信息
            ServiceTariff faultTariff = faultTariffBService.getTariffByChannelIdAndProductIdAndShowTypeAndType(channelId, productId, ProductDict.TRIFF_TYPE_SERVICE, showType, type);

            // 产品不支持一口价
            if (Objects.isNull(faultTariff)) {
                log.info(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_NULL + "");
                productPriceDRO.setFixedPrice(GlobalConsts.NO);
                return productPriceDRO;
            }

            // 查询价格表是否有默认的一口价服务项
            ProductServiceItemExcutePriceResultVo productFaultItemExcutePriceResultVo =
                    productBService.getDaultPriceItem(ProductDict.TRIFF_TYPE_SERVICE, servProduct, showType, channelId, type, brandId, baseArea.getAreaId());
            if (Objects.nonNull(productFaultItemExcutePriceResultVo)) {
                ProductPriceDRO priceDRO = this.setFixedPriceMsg(productPriceDRO, productFaultItemExcutePriceResultVo);
                priceDRO.setPayType(payType);
                return priceDRO;
            } else {
                log.info("not exist default fixedPrice item");
                productPriceDRO.setFixedPrice(GlobalConsts.NO);
                return productPriceDRO;
            }
        }

        productPriceDRO.setFixedPrice(GlobalConsts.NO);
        return productPriceDRO;
    }


    @Override
    public List<ShowProductDefaultSimpleDRO> listDefaultShowProductsByShowProductIds(ShowProductDefaultSimpleDIO dio) {
        if (Objects.isNull(dio) || CollectionUtils.isEmpty(dio.getShowProductIdList()) || NumberUtil.isNullOrZero(dio.getChannelId()) || NumberUtil.isNullOrZero(dio.getCityId())) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 赛选出符合条件的前台产品集合
        ServProductQuery query = new ServProductQuery();
        query.setProductIds(dio.getShowProductIdList());
        query.setBizType(dio.getBizType());
        query.setShowType(ProductDict.EC_PRODUCT_TYPE);
        List<Integer> showProductIdList = Optional.ofNullable(servProductService.listByQuery(query)).orElse(Collections.emptyList())
                .stream()
                .map(ServProduct::getProductId)
                .distinct()
                .collect(Collectors.toList());
        log.info("showProductIdList:{}", showProductIdList);
        dio.setShowProductIdList(showProductIdList);

        // 渠道城市开通的所有前台产品
        List<Integer> channelSupportProductIds = channelCategBService.listChannelShowProductsByChannelIdAndCityId(dio.getChannelId(), dio.getCityId());
        log.info("channelSupportProductIds:{}", channelSupportProductIds);

        // 当前产品的二级分类集合
        Set<Integer> productCategSet = new HashSet<>();
        Set<Integer> productServSet = new HashSet<>();
        Map<String, List<ShowProductDefaultSimpleDRO>> showProductDefaultSimpleDROMap = createRetDROList(productCategSet, productServSet, dio.getShowProductIdList());
        List<ServProduct> theSameCategProducts = listSameCategProducts(productCategSet, productServSet, dio.getBizType());

        // 二级分类对应的通用产品
        Map<String, ServProduct> defaultProductMap = new HashMap<>();
        // 二级分类下的非通用产品
        Map<String, List<ServProduct>> noneDefaultProduct = new HashMap<>();
        // 满足条件的所有产品id
        List<Integer> allProductIds = listAvaliableProductIds(theSameCategProducts, channelSupportProductIds, defaultProductMap, noneDefaultProduct);
        log.info("allProductIds:{}", allProductIds);
        // 有可能传递过来的产品id是禁用的，上述步骤会过滤禁用的产品，和渠道支持的前台产品不一致，特殊处理
        allProductIds.addAll(dio.getShowProductIdList());
        // 产品图片
        List<ServProductPicture> list = servProductPictureService.listByProductIds(allProductIds.stream().distinct().collect(Collectors.toList()));
        Map<Integer, String> mapPicture = list.stream().collect(Collectors.toMap(e -> e.getProductId(), e -> e.getSmallPicture() == null ? "" : e.getSmallPicture()));
        // 对最终产品进行归并
        return listFinalResult(showProductDefaultSimpleDROMap, defaultProductMap, noneDefaultProduct, mapPicture);
    }

    /**
     * 描述: 获取产品默认服务项
     *
     * @param tariffType  价格表类型
     * @param servProduct 产品
     * @param showType    产品展示类型:1.后台，2.前台，3.计价器
     * @param channelId   渠道ID
     * @param type        1保外，2.保内
     * @param brandId     品牌ID
     * @param cityId      城市ID
     * @return ProductServiceItemExcutePriceResultVo 默认服务项以及其价格信息
     * @auther tanghongjun
     * @since 2020/3/28 14:55
     */
    @Override
    @Cacheable(cacheNames = "redis5m", key = "'item:dault:tarifftype:'+#p0+':product:'+#p1+':showtype:'+#p2+':channel:'+#p3+':type:'+#p4+':brand:'+#p5+':city:'+#p6", unless = "#result == null")
    public ProductServiceItemExcutePriceResultVo getDaultPriceItem(Integer tariffType, ServProduct servProduct, Integer showType, Integer channelId, Integer type, Integer brandId, Integer cityId) {
        // 查询价格表是否有默认的一口价服务项
        ProductServiceItemExcutePriceQueryVo queryVo = new ProductServiceItemExcutePriceQueryVo();
        queryVo.setPageSize(1000);
        queryVo.setTariffType(tariffType);
        queryVo.setProductId(servProduct.getProductId());
        queryVo.setShowType(showType);
        queryVo.setChannelId(channelId);
        queryVo.setBizType(type);
        queryVo.setBrandId(brandId);
        queryVo.setServCategId(servProduct.getServCategId());
        queryVo.setCategOneId(servProduct.getCategOneId());
        queryVo.setCategId(servProduct.getCategId());
        queryVo.setCityId(cityId);
        List<ProductServiceItemExcutePriceResultVo> productFaultItemExcutePriceResultVos = tariffProductBService.listByExcuteQuery(queryVo);
        ProductServiceItemExcutePriceResultVo productFaultItemExcutePriceResultVo;
        for (int i = 0; i < productFaultItemExcutePriceResultVos.size(); i++) {
            productFaultItemExcutePriceResultVo = productFaultItemExcutePriceResultVos.get(i);
            if (Objects.equals(productFaultItemExcutePriceResultVo.getGeneral(), GlobalConsts.YES)) {
                return productFaultItemExcutePriceResultVo;
            }
        }
        return null;
    }

    /**
     * 设置一口价信息
     *
     * @param productPriceDRO                     产品一口价信息
     * @param productFaultItemExcutePriceResultVo 产品默认服务项
     * @return productPriceDRO 产品一口价信息
     */
    private ProductPriceDRO setFixedPriceMsg(ProductPriceDRO productPriceDRO,
                                             ProductServiceItemExcutePriceResultVo productFaultItemExcutePriceResultVo) {
        productPriceDRO.setPrice(productFaultItemExcutePriceResultVo.getPrice());
        // 如果渠道城市都没有配置，直接返回不支持一口价
        productPriceDRO.setFixedPrice(GlobalConsts.NO);
        ItemDRO itemDRO = new ItemDRO();
        BeanUtils.copyProperties(productFaultItemExcutePriceResultVo, itemDRO);
        productPriceDRO.setItemDRO(itemDRO);

        productPriceDRO.setItemId(productFaultItemExcutePriceResultVo.getItemId());
        productPriceDRO.setExternalSettlementPrice(productFaultItemExcutePriceResultVo.getExternalSettlementPrice());
        productPriceDRO.setInternalSettlementPrice(productFaultItemExcutePriceResultVo.getInternalSettlementPrice());

        return productPriceDRO;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:guarantee:ids:'+#p0", unless = "#result == null")
    public List<ProductGuaranteeDRO> listProductGuaranteeByIdList(List<Integer> productIdList) {
        if (CollectionUtils.isEmpty(productIdList)) {
            log.info("参数不能为空");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        List<ProductGuarantee> productGuaranteeList = productGuaranteeService.listByProductIds(productIdList);
        List<ProductGuaranteeDRO> productGuaranteeDROList = productGuaranteeList.stream().map(productGuarantee -> {
            ProductGuaranteeDRO productGuaranteeDRO = new ProductGuaranteeDRO();
            BeanUtils.copyProperties(productGuarantee, productGuaranteeDRO);
            return productGuaranteeDRO;
        }).collect(Collectors.toList());
        return productGuaranteeDROList;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:picture:ids:'+#p0", unless = "#result == null")
    public List<ServProductPictureDRO> listProductPictureByIdList(List<Integer> productIdList) {
        if (CollectionUtils.isEmpty(productIdList)) {
            log.error("参数不能为空");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        List<ServProductPicture> servProductPictureList = servProductPictureService.listByProductIds(productIdList);
        List<ServProductPictureDRO> productPictureDROList = servProductPictureList.stream().map(servProductPicture -> {
            ServProductPictureDRO productPictureDRO = new ServProductPictureDRO();
            BeanUtils.copyProperties(servProductPicture, productPictureDRO);
            return productPictureDRO;
        }).collect(Collectors.toList());
        return productPictureDROList;
    }

    @Override
    public List<ProductBaseDRO> listByShowTypeAndServCategAndCategAndStatus(Integer showType, Integer servCategId, Integer categTwoId, Integer status) throws PlatException {
        if (Objects.isNull(showType) && showType < ProductConsts.ERP_PRODUCT_TYPE && showType > ProductConsts.ET_PRODUCT_TYPE) {
            log.error("产品类型有误showType, showType:{},errorCode:{}", showType, PlatErrorCodeDict.ERROR_CODE_PARAM_OUT_OF_RANGE_ERROR);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PARAM_OUT_OF_RANGE_ERROR);
        }

        List<ProductAllMsgVO> productAllMsgVOList = servProductService.listByShowTypeAndServCategAndCategAndStatus(showType, servCategId, categTwoId, status);
        if (CollectionUtils.isEmpty(productAllMsgVOList)) {
            log.error("没有产品信息,errorCode:{}", PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
        }

        List<ProductBaseDRO> productBaseDROList = productAllMsgVOList.stream().map(productAllMsgVO -> {
            ProductBaseDRO productBase = new ProductBaseDRO();
            BeanUtils.copyProperties(productAllMsgVO, productBase);
            return productBase;
        }).collect(Collectors.toList());
        return productBaseDROList;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:base:dio:'+#p0", unless = "#result == null")
    public List<ProductBaseDRO> listBaseDROByDIO(ProductDIO productDIO) {
        if (Objects.isNull(productDIO)) {
            log.error("listBaseDROByDIO参数为空");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        List<ProductBaseDRO> productBaseDROList;
        ProductBaseDRO productBaseDRO;
        ProductAllMsgVO productVO;

        // 如果有产品ID，直接根据产品Id查询基本信息
        if (NumberUtil.isPositiveInteger(productDIO.getProductId())) {
            productVO = productCache.findByKey(productDIO.getProductId());
            if (Objects.isNull(productVO)) {
                return Collections.emptyList();
            }
            productBaseDRO = new ProductBaseDRO();
            BeanUtils.copyProperties(productVO, productBaseDRO);
            productBaseDROList = Arrays.asList(productBaseDRO);
            return productBaseDROList;
        }

        // 如果有产品Id集合，直接根据产品ID集合查询产品基本信息
        if (CollectionUtils.isNotEmpty(productDIO.getProductIdList())) {
            List<ProductAllMsgVO> productAllMsgVOList = productCache.listByKeys(productDIO.getProductIdList());
            if (CollectionUtils.isEmpty(productAllMsgVOList)) {
                return Collections.emptyList();
            }
            productBaseDROList = productAllMsgVOList.stream().map(productAllMsgVO -> {
                ProductBaseDRO productBase = new ProductBaseDRO();
                BeanUtils.copyProperties(productAllMsgVO, productBase);
                return productBase;
            }).collect(Collectors.toList());
            return productBaseDROList;
        }

        // 根据其它条件查询产品信息
        ProductQuery productQuery = new ProductQuery();
        BeanUtils.copyProperties(productDIO, productQuery);

        if (NumberUtil.isPositiveInteger(productDIO.getBizType())) {
            productQuery.setBizType(productDIO.getBizType().toString());
        }


        if (NumberUtil.isNullOrZero(productDIO.getDefaultType()) && Objects.equals(productDIO.getShowType(), ProductConsts.EC_PRODUCT_TYPE)) {
            productQuery.setDefaultType(GlobalConsts.NO);
        }


        Integer channelId = productDIO.getChannelId();
        try {
            if (NumberUtil.isPositiveInteger(channelId)) {
                channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
                productQuery.setChannelId(channelId);
            }
        } catch (PlatException e) {
            return Collections.emptyList();
        }

        // 如果渠道和服务分类不为空，需要查询渠道开通的二级分类
        if (Objects.nonNull(channelId) && Objects.nonNull(productDIO.getShowType()) && Objects.nonNull(productDIO.getCityId())) {
            int showType = Objects.equals(ProductConsts.ERP_PRODUCT_TYPE, productDIO.getShowType()) ? ProductConsts.ERP_PRODUCT_TYPE : ProductConsts.EC_PRODUCT_TYPE;
            List<ServCategAndCategTwoQuery> servCategAndCategTwoQueryList =
                    channelCategBService.listServCategAndCategTwoQueryByChannelIdAndShowType(channelId, productDIO.getCityId(), showType);
            if (CollectionUtils.isEmpty(servCategAndCategTwoQueryList)) {
                return Collections.emptyList();
            }
            productQuery.setServCategAndCategTwoQueryList(servCategAndCategTwoQueryList);
        }
        Long s = System.currentTimeMillis();
        List<ProductAllMsgVO> productAllMsgVOList = productCache.listByProductQuery(productQuery);
        // 如果查询默认产品，没有默认产品则查询普通产品
        if (CollectionUtils.isEmpty(productAllMsgVOList) && Objects.equals(GlobalConsts.YES, productDIO.getDefaultType())) {
            productQuery.setDefaultType(GlobalConsts.NO);
            productAllMsgVOList = productCache.listByProductQuery(productQuery);
        }
        log.error("查询耗时1=={}=={}", (System.currentTimeMillis() - s), productAllMsgVOList.size());

        if (CollectionUtils.isEmpty(productAllMsgVOList)) {
            return Collections.emptyList();
        }

        if (CollectionUtils.isEmpty(productAllMsgVOList)) {
            return Collections.emptyList();
        }
        productBaseDROList = productAllMsgVOList.stream().map(productAllMsgVO -> {
            if (NumberUtil.isNotNullOrZero(productAllMsgVO.getChannelId())) {
                if (Objects.equals(productAllMsgVO.getProductType(), GlobalConsts.YES)
                        && !productAllMsgVO.getChannelId().equals(productDIO.getChannelId())) {
                    return null;
                }
            }
            ProductBaseDRO productBase = new ProductBaseDRO();
            BeanUtils.copyProperties(productAllMsgVO, productBase);
            return productBase;
        }).filter(x -> Objects.nonNull(x)).collect(Collectors.toList());
        return productBaseDROList;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'check:tariff:product:'+#p0+':channel:'+#p1+':showtype:'+#p2+':bizType:'+#p3", unless = "#result == null")
    public Boolean checkTariffByProductIdAndShowType(Integer productId, Integer channelId, Integer showType, Integer bizType) {
        ServProduct product = servProductService.findByKey(productId);
        if (Objects.isNull(product)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST + "", productId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_PRODUCT_RESULT_NOT_EXIST);
        }
        return checkTariffByProductIdAndShowType(product, channelId, showType, bizType);
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:page:base:dio:'+#p0", unless = "#result == null")
    public List<ProductBaseDRO> listProductPageByDio(ProductDIO query) {
        if (Objects.isNull(query)) {
            log.error("入参不能为空");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        BeanCopier copierQuery = BeanCopier.create(ProductDIO.class, ServProductQuery.class, false);
        ServProductQuery servProductQuery = new ServProductQuery();
        copierQuery.copy(query, servProductQuery, null);

        // 判断渠道是否开通分类，如果已开通则取当前渠道，反之取上级渠道信息
        try {
            if (NumberUtil.isPositiveInteger(query.getChannelId())) {
                int channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(query.getChannelId());
                servProductQuery.setChannelId(channelId);
            }
        } catch (PlatException e) {
            return Collections.emptyList();
        }

        servProductQuery.setPageSize(query.getPageSize());
        servProductQuery.setPagesNumber(query.getPageNum());
        servProductQuery.setPageIndex(query.getPageNum());
        servProductQuery.setName(query.getKeyWord());

        // 如果渠道和服务分类不为空，需要查询渠道开通的二级分类
        if (Objects.nonNull(query.getChannelId()) && Objects.nonNull(query.getShowType()) && Objects.nonNull(query.getCityId())) {
            int showType = Objects.equals(ProductConsts.ERP_PRODUCT_TYPE, query.getShowType()) ? ProductConsts.ERP_PRODUCT_TYPE : ProductConsts.EC_PRODUCT_TYPE;
            List<ServCategAndCategTwoQuery> servCategAndCategTwoQueryList =
                    channelCategBService.listServCategAndCategTwoQueryByChannelIdAndShowType(query.getChannelId(), query.getCityId(), showType);
            if (CollectionUtils.isEmpty(servCategAndCategTwoQueryList)) {
                return Collections.emptyList();
            }
            servProductQuery.setServCategAndCategTwoQueryList(servCategAndCategTwoQueryList);
        }

        int count = servProductService.countByQuery(servProductQuery);
        servProductQuery.setTotalCount(count);
        List<ServProduct> servProductList = servProductService.listPageByQuery(servProductQuery);

        if (CollectionUtils.isEmpty(servProductList)) {
            return Collections.emptyList();
        }

        BaseCategoryQuery queryB = new BaseCategoryQuery();
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);

        BeanCopier copier = BeanCopier.create(ServProduct.class, ProductBaseDRO.class, false);
        List<ProductBaseDRO> dros = servProductList.stream().map(servProduct -> {
            ProductBaseDRO servProductDRO = new ProductBaseDRO();
            copier.copy(servProduct, servProductDRO, null);
            servProductDRO.setServCategName(servProductBService.findServCategNameById(servCategories, servProductDRO.getServCategId(), servProductDRO.getShowType()));
            servProductDRO.setCategOneName(servProductBService.findBaseCategNameById(baseCategorieall, servProductDRO.getCategOneId()));
            servProductDRO.setCategName(servProductBService.findBaseCategNameById(baseCategorieall, servProductDRO.getCategId()));
            return servProductDRO;
        }).collect(Collectors.toList());
        return dros;
    }

    @Override
    public List<ProductBaseDRO> listByChannelIdAndProductDIO(Integer channelId, ProductDIO servProductDIO) {
        if (Objects.isNull(servProductDIO) || NumberUtil.isNullOrZero(channelId)) {
            log.error("入参不能为空,servProductDIO={},channelId={}", servProductDIO, channelId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        // 判断渠道是否开通分类，如果已开通则取当前渠道，反之取上级渠道信息
        try {
            if (NumberUtil.isPositiveInteger(channelId)) {
                channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
                servProductDIO.setChannelId(channelId);
            }
        } catch (PlatException e) {
            return Collections.emptyList();
        }


        ServProductQuery servProductQuery = new ServProductQuery();
        BeanUtils.copyProperties(servProductDIO, servProductQuery);
        servProductQuery.setPagesNumber(servProductDIO.getPageNum());
        servProductQuery.setPageSize(servProductDIO.getPageSize());
        servProductQuery.setPageIndex(servProductDIO.getPageNum());
        servProductQuery.setName(servProductDIO.getKeyWord());
        List<ServProduct> servProducts = servProductBService.listByChannelIdAndProductQuery(channelId, servProductQuery);

        BaseCategoryQuery queryB = new BaseCategoryQuery();
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);
        BeanCopier copier = BeanCopier.create(ServProduct.class, ProductBaseDRO.class, false);
        List<ProductBaseDRO> dros = servProducts.stream().map(servProduct -> {
            ProductBaseDRO servProductDRO = new ProductBaseDRO();
            copier.copy(servProduct, servProductDRO, null);
            servProductDRO.setServCategName(servProductBService.findServCategNameById(servCategories, servProductDRO.getServCategId(), servProductDRO.getShowType()));
            servProductDRO.setCategOneName(servProductBService.findBaseCategNameById(baseCategorieall, servProductDRO.getCategOneId()));
            servProductDRO.setCategName(servProductBService.findBaseCategNameById(baseCategorieall, servProductDRO.getCategId()));
            return servProductDRO;
        }).collect(Collectors.toList());
        return dros;
    }

    @Override
    public Integer countByDio(ProductDIO query) {
        if (Objects.isNull(query)) {
            log.error("入参不能为空,query={}", query);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        BeanCopier copierQuery = BeanCopier.create(ProductDIO.class, ServProductQuery.class, false);
        ServProductQuery servProductQuery = new ServProductQuery();
        copierQuery.copy(query, servProductQuery, null);
        servProductQuery.setPageSize(query.getPageSize());
        servProductQuery.setPagesNumber(query.getPageNum());
        servProductQuery.setName(query.getKeyWord());

        // 判断渠道是否开通分类，如果已开通则取当前渠道，反之取上级渠道信息
        try {
            if (NumberUtil.isPositiveInteger(query.getChannelId())) {
                int channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(query.getChannelId());
                servProductQuery.setChannelId(channelId);
            }
        } catch (PlatException e) {
            return 0;
        }

        Integer count = servProductService.countByQuery(servProductQuery);
        return count;
    }

    @Override
    public Integer countByChannelIdAndProductDIO(Integer channelId, ProductDIO servProductDIO) {
        if (Objects.isNull(servProductDIO) || !NumberUtil.isPositiveInteger(channelId)) {
            log.error("入参不能为空，channelId={},servProductDIO={}", channelId, servProductDIO);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        BeanCopier copierQuery = BeanCopier.create(ProductDIO.class, ServProductQuery.class, false);
        ServProductQuery servProductQuery = new ServProductQuery();
        copierQuery.copy(servProductDIO, servProductQuery, null);
        servProductQuery.setName(servProductDIO.getKeyWord());

        // 判断渠道是否开通分类，如果已开通则取当前渠道，反之取上级渠道信息
        try {
            if (NumberUtil.isPositiveInteger(channelId)) {
                channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
            }
        } catch (PlatException e) {
            return 0;
        }

        Integer count = servProductBService.countByChannelIdAndProductQuery(channelId, servProductQuery);
        return count;
    }

    @Override
    public Boolean checkTariffByProductIdAndShowType(ServProduct product, Integer channelId, Integer showType, Integer bizType) {
        // 后台产品是否支持计价器
        if (Objects.equals(showType, ProductConsts.ERP_PRODUCT_TYPE)) {
            return checkTariffByErpProduct(product, channelId, bizType);
        }
        // 前台产品是否支持计价器
        if (Objects.equals(showType, ProductConsts.EC_PRODUCT_TYPE)) {
            return checkTariffByEcProduct(product, channelId, bizType);
        }
        // 计价器产品是否支持计价器
        if (Objects.equals(showType, ProductConsts.ET_PRODUCT_TYPE)) {
            return checkTariffByEtProduct(product, channelId, bizType);
        }
        return false;
    }

    private boolean isUpperShelf(ServProduct product) {
        return !isNotUpperShelf(product);
    }

    private boolean isNotUpperShelf(ServProduct product) {
        return Objects.isNull(product.getStatus()) || GlobalConsts.YES != product.getStatus().intValue();
    }

    private boolean isNotOpenTariff(ServProduct product) {
        return Objects.isNull(product.getTariffStatus()) || GlobalConsts.YES != product.getTariffStatus().intValue();
    }

    private boolean isNotHaveFaultTariff(ServProduct product, Integer channelId, Integer bizType) {
        ServiceTariff faultTariff =
                faultTariffBService.getTariffByChannelIdAndProductIdAndShowTypeAndType(channelId, product.getProductId(), ProductDict.TRIFF_TYPE_TARIFF, product.getShowType(), bizType);
        return faultTariff == null;
    }

    private boolean checkTariffByErpProduct(ServProduct product, Integer channelId, Integer bizType) {
        if (isNotUpperShelf(product)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_STATUS_NO + "该产品未上架, productId:{}", product.getProductId());
            return false;
        }
        if (isNotOpenTariff(product)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "该产品未开通计价器, productId:{}", product.getProductId());
            return false;
        }

        if (isNotHaveFaultTariff(product, channelId, bizType)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TARIFF_NULL + "该产品没有可用的计价器价格表, productId:{}", product.getProductId());
            return false;
        }
        ServProduct tariffProduct = servProductService.findTariffProductByBackProductId(product.getProductId());
        if (Objects.isNull(tariffProduct)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_TRIAFF_PRODUCT + "该产品没有关联计价器产品, productId:{}", product.getProductId());
            return false;
        }
        if (isNotUpperShelf(tariffProduct)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_TRAIFF_PRODUCT_STATUS_NO + "该产品关联的计价器产品未上架, productId:{}， tariffProductId:{}", product.getProductId(), tariffProduct.getProductId());
            return false;
        }
        ServProduct showProduct = servProductService.findShowProductByBackProductId(product.getProductId());
        if (Objects.isNull(showProduct)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_RELATION + "该产品没有关联前台产品, productId:{}", product.getProductId());
            return false;
        }
        if (isNotUpperShelf(showProduct)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_SHOW_PRODUCT_STATUS_NO + "该产品关联的前台产品未上架, productId:{}， showProductId:{}", product.getProductId(), showProduct.getProductId());
            return false;
        }
        return true;
    }

    private boolean checkTariffByEcProduct(ServProduct product, Integer channelId, Integer bizType) {
        if (isNotUpperShelf(product)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_STATUS_NO + "该产品未上架, productId:{}", product.getProductId());
            return false;
        }
        List<ServProduct> backProductList = servProductService.listBackProductByShowProductId(product.getProductId());
        if (CollectionUtils.isEmpty(backProductList)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_RELATION + "该产品没有关联后台产品, productId:{}", product.getProductId());
            return false;
        }
        List<Integer> backProductIds = backProductList.stream().filter(backProduct -> {
            if (isNotUpperShelf(backProduct)) {
                return false;
            }
            if (isNotOpenTariff(backProduct)) {
                return false;
            }
            if (isNotHaveFaultTariff(backProduct, channelId, bizType)) {
                return false;
            }
            return true;
        }).map(ServProduct::getProductId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(backProductIds)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "该产品关联的后台产品不支持计价, productId:{}", product.getProductId());
            return false;
        }
        List<ServProduct> tariffProductList = servProductService.listTariffProductByBackProductId(backProductIds);
        if (CollectionUtils.isEmpty(tariffProductList)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_TRIAFF_PRODUCT + "该产品没有关联的计价器产品, productId:{}", product.getProductId());
            return false;
        }
        List<Integer> tariffProductIds = tariffProductList.stream().filter(tariffProduct -> isUpperShelf(tariffProduct)).map(ServProduct::getProductId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(tariffProductIds)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "该产品关联的计价器产品不支持计价, productId:{}", product.getProductId());
            return false;
        }
        return true;
    }

    private boolean checkTariffByEtProduct(ServProduct product, Integer channelId, Integer bizType) {
        if (isNotUpperShelf(product)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_STATUS_NO + "该产品未上架, productId:{}", product.getProductId());
            return false;
        }
        List<ServProduct> backProductList = servProductService.listBackProductByTariffProductId(product.getProductId());
        if (CollectionUtils.isEmpty(backProductList)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_RELATION + "该产品没有关联后台产品, productId:{}", product.getProductId());
            return false;
        }
        List<Integer> backProductIds = backProductList.stream().filter(backProduct -> {
            if (isNotUpperShelf(backProduct)) {
                return false;
            }
            if (isNotOpenTariff(backProduct)) {
                return false;
            }
            if (isNotHaveFaultTariff(backProduct, channelId, bizType)) {
                return false;
            }
            return true;
        }).map(ServProduct::getProductId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(backProductIds)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "该产品关联的后台产品不支持计价, productId:{}", product.getProductId());
            return false;
        }
        List<ServProduct> showProductList = servProductService.listShowProductByBackProductId(backProductIds);
        if (CollectionUtils.isEmpty(showProductList)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NO_RELATION + "该产品没有关联的前台产品, productId:{}", product.getProductId());
            return false;
        }
        List<Integer> showProductIds = showProductList.stream().filter(showProduct -> isUpperShelf(showProduct)).map(ServProduct::getProductId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(showProductIds)) {
            log.debug(PlatErrorCodeDict.ERROR_CODE_PRODUCT_NOT_SUPPORT_TRIAFF + "该产品关联的前台产品不支持计价, productId:{}", product.getProductId());
            return false;
        }
        return true;
    }

    private List<ShowProductDefaultSimpleDRO> listFinalResult(Map<String, List<ShowProductDefaultSimpleDRO>> showProductDefaultSimpleDROMap, Map<String, ServProduct> defaultProductMap,
                                                              Map<String, List<ServProduct>> noneDefaultProduct, Map<Integer, String> mapPicture) {
        List<ShowProductDefaultSimpleDRO> retList = new ArrayList<>();
        // 对最终产品进行归并
        showProductDefaultSimpleDROMap.forEach((k, v) -> {
            // 通用产品
            ServProduct defaultProduct = defaultProductMap.get(k);
            // 通用产品下的非通用产品
            List<ServProduct> categProducts = noneDefaultProduct.get(k);
            List<ShowProductDefaultSimpleDRO> subs = listSubProducts(defaultProduct, categProducts, mapPicture);
            v.forEach(e -> {
                // 对当前产品默认产品赋值
                if (Objects.nonNull(defaultProduct)) {
                    e.setDefaultProductId(defaultProduct.getProductId());
                    e.setDefaultProductName(defaultProduct.getName());
                    e.setDefaultProductPicture(mapPicture.get(defaultProduct.getProductId()));
                }
                // 对当前产品非默认产品赋值
                e.setNoneDefaultProducts(subs);
                e.setProductPicture(mapPicture.get(e.getProductId()));
            });
            retList.addAll(v);
        });
        return retList;
    }

    private List<ServProduct> listSameCategProducts(Set<Integer> productCategSet, Set<Integer> productServSet, Integer bizType) {
        // 查询二级分类下所有启用状态的产品（包括默认产品）
        List<Integer> showCategIdList = new ArrayList<>(productCategSet);
        List<Integer> showServIdList = new ArrayList<>(productServSet);
        ServProductQuery query = new ServProductQuery();
        query.setCategIds(showCategIdList);
        query.setServCategIds(showServIdList);
        query.setShowType(ProductDict.EC_PRODUCT_TYPE);
        query.setStatus(GlobalConsts.YES);
        query.setBizType(bizType);
        // query.setDefaultType(GlobalConsts.YES);
        List<ServProduct> products = servProductService.listByQuery(query);
        return products;
    }

    private List<Integer> listAvaliableProductIds(List<ServProduct> products, List<Integer> channelSupportProductIds,
                                                  Map<String, ServProduct> defaultProductMap, Map<String, List<ServProduct>> noneDefaultProduct) {
        // 满足条件的所有产品id
        List<Integer> allProductIds = new ArrayList<>();
        for (ServProduct product : products) {
            String key = product.getServCategId() + "_" + product.getCategId();
            // 二级分类下的通用产品
            if (Objects.equals(product.getDefaultType(), GlobalConsts.YES)) {
                defaultProductMap.putIfAbsent(key, product);
                allProductIds.add(product.getProductId());
            } else {
                // 非通用产品是否是渠道配置下开通的产品
                if (!channelSupportProductIds.contains(product.getProductId())) {
                    continue;
                }
                allProductIds.add(product.getProductId());
                List<ServProduct> categProducts = noneDefaultProduct.get(key);
                if (CollectionUtils.isEmpty(categProducts)) {
                    categProducts = new ArrayList<>();
                    categProducts.add(product);
                    noneDefaultProduct.put(key, categProducts);
                } else {
                    categProducts.add(product);
                }
            }
        }
        return allProductIds;
    }

    private Map<String, List<ShowProductDefaultSimpleDRO>> createRetDROList(Set<Integer> productCategSet, Set<Integer> productServSet, List<Integer> productIds) {
        Map<String, List<ShowProductDefaultSimpleDRO>> showProductDefaultSimpleDROMap = new HashMap<>(productIds.size());
        // 当前产品集合
        List<ServProduct> productList = servProductService.listByIdList(productIds);
        for (ServProduct retProduct : productList) {
            String key = retProduct.getServCategId() + "_" + retProduct.getCategId();
            productCategSet.add(retProduct.getCategId());
            productServSet.add(retProduct.getServCategId());
            ShowProductDefaultSimpleDRO defaultSimpleDRO = new ShowProductDefaultSimpleDRO();
            defaultSimpleDRO.setProductId(retProduct.getProductId());
            defaultSimpleDRO.setProductName(retProduct.getName());
            List<ShowProductDefaultSimpleDRO> categProductList = showProductDefaultSimpleDROMap.get(key);
            if (CollectionUtils.isEmpty(categProductList)) {
                categProductList = new ArrayList<>();
                categProductList.add(defaultSimpleDRO);
                showProductDefaultSimpleDROMap.put(key, categProductList);
            } else {
                categProductList.add(defaultSimpleDRO);
            }
        }
        return showProductDefaultSimpleDROMap;
    }

    private List<ShowProductDefaultSimpleDRO> listSubProducts(ServProduct defaultProduct, List<ServProduct> categProducts, Map<Integer, String> mapPicture) {
        if (CollectionUtils.isEmpty(categProducts)) {
            return null;
        }
        return categProducts.stream().map(e -> {
            ShowProductDefaultSimpleDRO defaultSimpleDRO = new ShowProductDefaultSimpleDRO();
            defaultSimpleDRO.setProductId(e.getProductId());
            defaultSimpleDRO.setProductName(e.getName());
            if (Objects.nonNull(defaultProduct)) {
                defaultSimpleDRO.setDefaultProductName(defaultProduct.getName());
                defaultSimpleDRO.setDefaultProductId(defaultProduct.getProductId());
                defaultSimpleDRO.setDefaultProductPicture(mapPicture.get(defaultProduct.getProductId()));
            }
            defaultSimpleDRO.setProductPicture(mapPicture.get(e.getProductId()));
            return defaultSimpleDRO;
        }).collect(Collectors.toList());
    }

    /**
     * 描述：定渠道Id和城市Id与给定商品Id进行筛选
     *
     * @param dio 渠道城市产品Id集合
     * @return 产品集合
     * @auther liuyong
     * @since 20201/4/22 16:20
     */
    @Override
    public List<Integer> getShowProductIds(ShowProductDefaultSimpleDIO dio) {
        if (Objects.isNull(dio) || CollectionUtils.isEmpty(dio.getShowProductIdList()) || NumberUtil.isNullOrZero(dio.getChannelId()) || NumberUtil.isNullOrZero(dio.getCityId())) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        List<Integer> listChannelProductIds = channelCategBService.listChannelShowProductsByChannelIdAndCityId(dio.getChannelId(), dio.getCityId());
        dio.getShowProductIdList().retainAll(listChannelProductIds);
        return dio.getShowProductIdList();
    }


}
